package com.logicfish.owlet.ext.jenasesame;

import org.openjena.jenasesame.JenaSesame;
import org.openrdf.model.Resource;
import org.openrdf.repository.RepositoryConnection;

import com.hp.hpl.jena.query.Dataset;
import com.hp.hpl.jena.rdf.model.Model;
import com.logicfishsoftware.owlet.app.Application;
import com.logicfishsoftware.owlet.app.ApplicationException;
import com.logicfishsoftware.owlet.app.Operator;
import com.logicfishsoftware.owlet.app.runtime.RuntimeApplication;

/**
 * Consider making this class final.
 * -- It should be an extension of an owlet-jena class.
 */
public abstract class JenaSesameApp<T extends JenaSesameApp<T,U>.JenaSesameAtom,U extends JenaSesameApp<T,U>.JenaSesameContext>
extends RuntimeApplication<T,U> 
implements Application<JenaSesameApp.JenaSesameOperator<U>>
{
	
    /**
	 * @author logicfish@gmail.com
	 *
	 */
	public static interface JenaSesameOperator<V> 
	extends Operator<V> {

		/**
		 * @return
		 */
		abstract RepositoryConnection getConnection() throws ApplicationException;
		
		public boolean application(V context) throws Exception;

	}

//	public static interface DatasetDelegate<V> 
//	extends JenaSesameOperator<V> {
//		/**
//		 * @param context
//		 * @param dataset
//		 * @return
//		 */
////		abstract public boolean application(V context, Dataset dataset);
//	}
//
//	public static interface ModelOperator<V> 
//	extends JenaSesameOperator<V> {
//		Resource getResource();
//		/**
//		 * @param context
//		 * @param model
//		 * @return
//		 */
////		abstract boolean application(V context, Model model);
//	}
	
	/**
	 * @author logicfish@gmail.com
	 *
	 */
	public abstract class JenaSesameContext 
	extends RuntimeApplication<T,U>.ApplicationContext {

		private T atomic;

		/**
		 * @param atomic
		 */
		protected JenaSesameContext(T atomic) {
			this.atomic = atomic;
		}


		/* (non-Javadoc)
		 * @see com.logicfishsoftware.owlet.app.app.ApplicationRuntime.ApplicationFrame#dispose()
		 */
		protected void dispose() throws ApplicationException {
//			this.atomic.dispose();
		}
		
		Dataset createDataset() throws ApplicationException {
			return JenaSesame.createDataset(atomic.getConnection());
		}
		Model createModel(Resource context) throws ApplicationException {
			return JenaSesame.createModel(atomic.getConnection(),context);
		}
		Model createModel() throws ApplicationException {
			return JenaSesame.createModel(atomic.getConnection());
		}

	}
	
	/**
	 * @author logicfish@gmail.com
	 *
	 */
	public abstract class JenaSesameAtom extends RuntimeApplication<T,U>.ApplicationAtom {
		JenaSesameOperator<U> delegate;
//		private Dataset dataset;
//		private Model model;

		/**
		 * @param atomic
		 */
		protected JenaSesameAtom(JenaSesameOperator<U> atomic) {
			this.delegate = atomic;
		}

		/**
		 * @param delegate
		 */
		protected JenaSesameAtom(Operator<? super U> delegate) {
			this((JenaSesameOperator<U>) delegate);
		}

		/**
		 * 
		 */
//		protected void dispose() {
//			delegate = null;
//			if(dataset!=null) 
//				dataset.close();
//			if(model!=null)
//				model.close();
//		}

		/* (non-Javadoc)
		 * @see com.logicfishsoftware.owlet.app.app.ApplicationRuntime.ApplicationAtom#application(com.logicfishsoftware.owlet.app.app.ApplicationRuntime.ApplicationFrame)
		 */
		@Override
		protected boolean application(U context) throws Exception {
//			if(delegate instanceof DatasetDelegate) {
//				this.dataset = context.createDataset();
//				return ((DatasetDelegate<U>) delegate).application(context,dataset);
//			}
//			if(delegate instanceof ModelOperator) {
//				Resource resource = ((ModelOperator<?>)delegate).getResource();
//				if(resource!=null)
//					this.model = context.createModel(resource); 
//				else 
//					this.model = context.createModel();
//				return ((ModelOperator<U>) delegate).application(context,model);
//			}
//			throw new ApplicationException("Unknown delegate type " + delegate.getClass().getName());
			return delegate.application(context);
		}

		/* (non-Javadoc)
		 * @see com.logicfishsoftware.owlet.app.app.ApplicationRuntime.ApplicationAtom#proceed()
		 */
		@Override
		protected T proceed() throws ApplicationException {
			Operator<U> tail = delegate.proceed();
			delegate = null;
			if(tail!=null)
				return createAtom(tail);
			return null;
		}

		protected RepositoryConnection getConnection() throws ApplicationException {
			return delegate.getConnection();
		}
	}

	/* (non-Javadoc)
	 * @see com.logicfishsoftware.owlet.app.app.Application#apply(java.lang.Object)
	 */
	public boolean enter(JenaSesameOperator<U> atomic) throws ApplicationException {
//		return apply((T)new JenaSesameAtom(atomic));
		return enter(createAtom(atomic));
	}

	/**
	 * @param tail
	 * @return
	 */
//	abstract protected T createAtom(Operator<U> tail);

//	/* (non-Javadoc)
//	 * @see com.logicfishsoftware.owlet.app.app.ApplicationRuntime#createFrame(com.logicfishsoftware.owlet.app.app.ApplicationRuntime.ApplicationAtom)
//	 */
//	@SuppressWarnings("unchecked")
//	@Override
//	protected U createAppContext(T atomic) {
//		return (U) new JenaSesameContext(atomic) {
//		};
//	}
//	

	public static void main( String[] args )
    {
        System.out.println( "Hello World!" );
    }

}
